//
//  TestFile.m
//  iOS Sample Code
//
//  Created by lei yu on 11-12-8.
//  Copyright (c) 2011年 lancet. All rights reserved.
//

#import "TestFile.h"

@implementation TestFile


/*
 
 Method Description
 -(NSData *) contentsAtPath: path Reads data from a file
 -(BOOL) createFileAtPath: path Writes data to a file contents: (NSData *) data
 attributes: attr
 -(BOOL) removeItemAtPath: path Removes a file error: err
 -(BOOL) moveItemAtPath: from Renames or moves a file (to cannot toPath: to error: err already exist)
 -(BOOL) copyItemAtPath: from Copies a file (to cannot already exist) toPath: to error: err
 -(BOOL) contentsEqualAtPath: path1 Compares contents of two files andPath: path2
 -(BOOL) fileExistsAtPath: path Tests for file existence
 -(BOOL) isReadableFileAtPath: path Tests whether file exists and can be read
 -(BOOL) isWritableFileAtPath: path Tests whether file exists and can be written
 -(NSDictionary *) Gets attributes for file attributesOfItemAtPath: path
 error: err
 -(BOOL) setAttributesOfItemAtPath: Changes file attributes attr error: err
 
 
 
 
 
 
 -(NSString *) currentDirectoryPath Gets the current directory
 -(BOOL) changeCurrentDirectoryPath: path Changes the current directory 
 -(BOOL) copyItemAtPath: from toPath: to error: err Copies a directory structure (to cannot previously exist)
 -(BOOL) createDirectoryAtPath:path withIntermediateDirectories: (BOOL) flag attributes: attr Creates a new directory 
 -(BOOL) fileExistsAtPath: path isDirectory: (BOOL *) flag Tests whether the file exists and is a directory (YES/NO result is stored in flag)
 -(NSArray *) contentsOfDirectoryAtPath: path error: err Lists the contents of the directory 
 -(NSDirectoryEnumerator *)enumeratorAtPath: path Enumerates the contents of the directory 
 -(BOOL) removeItemAtPath: path error: err Deletes an empty directory
 -(BOOL) moveItemAtPath: from toPath: to error: err Renames or moves a directory (to cannot previously exist)
 
 */



- (void)testFileManager
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSString  *fName = @"testfile";
    NSFileManager *fm;
    NSDictionary *attr;
    // Need to create an instance of the file manager 
    // Let's make sure our test file exists first
    
    fm = [NSFileManager defaultManager];
    
    if ([fm fileExistsAtPath: fName] == NO) { 
        NSLog(@"File doesn't exist!");
        
    }
    //now lets make a copy
    if ([fm copyItemAtPath: fName toPath: @"newfile" error: NULL] == NO) { 
        NSLog(@"File Copy failed!");
    }
    // Now let's test to see if the two files are equal
    if ([fm contentsEqualAtPath: fName andPath: @"newfile"] == NO) {
        
        NSLog(@"Files are Not Equal!");
    }
    // Now lets rename the copy
    if ([fm moveItemAtPath: @"newfile" toPath: @"newfile2" error: NULL] == NO){
        NSLog(@"File rename Failed");
    }
    // get the size of the newfile2
    if ((attr = [fm attributesOfItemAtPath: @"newfile2" error: NULL]) == nil) {
        NSLog(@"Couldn't get file attributes!");
    }
    NSLog(@"File size is %llu bytes",
          [[attr objectForKey: NSFileSize] unsignedLongLongValue]);
    // And finally, let's delete the original file
    if ([fm removeItemAtPath: fName error: NULL] == NO) { 
        NSLog(@"file removal failed");
    }
    NSLog(@"All operations were successful");
    // Display the contents of the newly-created file
    NSLog(@"%@", [NSString stringWithContentsOfFile:
                  @"newfile2" encoding:NSUTF8StringEncoding error:NULL]);
    [pool drain];
}



-(void)testNSDataReading{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSFileManager *fm;
    NSData *fileData;
    fm = [NSFileManager defaultManager];
    // Read the file newfile2
    fileData = [fm contentsAtPath: @"newfile2"];
    if (fileData == nil) {
        NSLog (@"File read failed!");
    }
    // Write the data to newfile3
    if ([fm createFileAtPath: @"newfile3" contents: fileData attributes: nil] == NO) { 
        NSLog (@"Couldn't create the copy!");        
    }
    NSLog (@"File copy was successful!");
    [pool drain];
}


-(void)testDirectoryOperations{
    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSString  *dirName = @"testdir";
    NSString *path;
    NSFileManager *fm;
    // Need to create an instance of the file manager
    fm = [NSFileManager defaultManager];
    // Get current directory
    path = [fm currentDirectoryPath];
    NSLog (@"Current directory path is %@", path);
    // Create a new directory
    if ([fm createDirectoryAtPath: dirName withIntermediateDirectories: YES attributes: nil error: NULL] == NO) {
        NSLog (@"Couldn't create directory!"); 
    }
    // Rename the new directory
    if ([fm moveItemAtPath: dirName toPath: @"newdir" error: NULL] == NO) { NSLog (@"Directory rename failed!");
        
    }
    // Change directory into the new directory
    if ([fm changeCurrentDirectoryPath: @"newdir"] == NO) { NSLog (@"Change directory failed!");
        
    }
    // Now get and display current working directory
    path = [fm currentDirectoryPath];
    NSLog (@"Current directory path is %@", path);
    NSLog (@"All operations were successful!");
    [pool drain];
    
    
}

-(void)testDirectoryEnumeration{
    NSAutoreleasePool  * pool = [[NSAutoreleasePool alloc] init];
    NSString *path;
    NSFileManager  *fm;
    NSDirectoryEnumerator *dirEnum;
    NSArray *dirArray;
    BOOL flag;
    
    // Need to create an instance of the file manager
    fm = [NSFileManager defaultManager]; // Get current working directory path
    path = [fm currentDirectoryPath];
    
    // Enumerate the directory
    dirEnum = [fm enumeratorAtPath: path];
    NSLog (@"Contents of %@", path);
    
    
    while ((path = [dirEnum nextObject]) != nil) { 
        NSLog (@"%@", path);
        [fm fileExistsAtPath: path isDirectory: &flag];
        if (flag == YES)
            [dirEnum skipDescendents];
    }
    
    // Another way to enumerate a directory 
    dirArray = [fm contentsOfDirectoryAtPath:[fm currentDirectoryPath] error: NULL];
    NSLog (@"Contents using contentsOfDirectoryAtPath:error:");
    for ( path in dirArray ){ 
        NSLog (@"%@", path);
    }
    [pool drain];
}
/*
 
 NSPathUtilities.h includes functions and category extensions to NSString to enable you to manipulate pathnames.
 
 
 
 
 
 Method Description 
 +(NSString *) pathWithComponents: Constructs a valid path from elements components in components 
 -(NSArray *) pathComponents Deconstructs a path into its constituent components 
 -(NSString *) lastPathComponent Extracts the last component in a path 
 -(NSString *) pathExtension Extracts the extension from the last component in a path 
 -(NSString *) stringByAppendingPathComponent: path  Adds path to the end of an existing path 
 -(NSString *) stringByAppendingPathExtension: ext Adds the specified extension to the  last component in the path 
 -(NSString *) stringByDeletingLastPathComponent Removes the last path component  
 -(NSString *) stringByDeletingPathExtension Removes the extension from the last  path component 
 -(NSString *) stringByExpandingTildeInPath Expands any tildes in the path to the  user’s home directory (~) or a specified user’s home directory (~user) 
 -(NSString *) stringByResolvingSymlinksInPath Attempts to resolve symbolic links in  the path 
 -(NSString *) stringByStandardizingPath Standardizes a path by attempting to resolve ~, .. (parent  directory), . (current directory), and symbolic links
 
 
 common path utility functions
 NSString *NSUserName (void) Returns the current user’s login name
 NSString *NSFullUserName (void) Returns the current user’s full username
 NSString *NSHomeDirectory (void) Returns the path to the current user’s home directory
 NSString *NSHomeDirectoryForUser (NSString *user) Returns the home directory for user 
 NSString *NSTemporaryDirectory (void) Returns the path to a directory that can be  used for creating a temporary file
 
 
 
 
 
 */
-(void)testNSPathUtilities{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *fName = @"path.m";
    NSFileManager *fm;
    NSString  *upath = @"~stevekochan/progs/../ch16/./path.m";
    NSString *path, *tempdir, *extension, *homedir, *fullpath;
    NSArray *components;
    fm = [NSFileManager defaultManager];
    // Get the temporary working directory
    tempdir = NSTemporaryDirectory ();
    NSLog (@"Temporary Directory is %@", tempdir);
    // Extract the base directory from current directory
    path = [fm currentDirectoryPath];
    NSLog (@"Base dir is %@", [path lastPathComponent]);
    // Create a full path to the file fName in current directory
    fullpath = [path stringByAppendingPathComponent: fName]; 
    NSLog (@"fullpath to %@ is %@", fName, fullpath);
    // Get the file name extension
    extension = [fullpath pathExtension];
    NSLog (@"extension for %@ is %@", fullpath, extension);
    // Get user's home directory
    homedir = NSHomeDirectory ();
    NSLog (@"Your home directory is %@", homedir);
    // Divide a path into its components
    components = [homedir pathComponents];
    for ( path in components ) {
        NSLog (@"%@", path);
    }
    // “Standardize" a path
    NSLog (@"%@ => %@",upath,[upath stringByStandardizingPath]);
    [pool drain];
}

/*
 
 Common iOS directories
 
 Documents Directory for writing application-specific data files (NSDocumentDirectory)
 Library/Caches  (NSCachesDirectory)  Directory for writing application-specific support files to persist between launches of the application. Files created in this directory are not backed up by iTunes
 tmp (use NSTemporaryDirecory()) Directory to write temporary files that can be removed  after your application terminates. You should remove files from this directory when no longer needed.
 Library/Preferences This directory contains application-specific preference files. Preference files are created, read, and modified using the NSUserDefaults class.
 
 
 The second argument to the function can be one of several values that specifies the directories to list, such as the user’s (as shown in the example), the system’s, or all directories.The last argument specifies whether to expand ~ characters in the path.
 
 
 The NSSearchPathForDirectoriesInDomains returns an array of paths.The array will contain a single element if you’re just looking for the user’s directory and can contain more than one element based on the value specified by the second argument.
 */
-(void)testSearchInDomain{
    
    NSArray *dirList = NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES);
    NSString *docDir = [dirList objectAtIndex: 0];
    NSLog(@"%@", [docDir stringByAppendingPathComponent: @"saveFile"]); 
}


/*
 
 Method Description
 +(NSFileHandle *)fileHandleForReadingAtPath: path Opens a file for reading 
 +(NSFileHandle *)fileHandleForWritingAtPath: path Opens a file for writing 
 +(NSFileHandle *)fileHandleForUpdatingAtPath: path  Opens a file for updating (reading and writing)
 -(NSData *) availableData Returns data available for reading from a device or channel
 -(NSData *) readDataToEndOfFile Reads the remaining data up to the end of the file (UINT_MAX) bytes max
 -(NSData *) readDataOfLength:(NSUInteger) bytes Reads a specified number of bytes from  the file
 -(void) writeData: data Writes data to the file
 -(unsigned long long) offsetInFile Obtains the current file offset
 -(void) seekToFileOffset: offset Sets the current file offset
 -(unsigned long long) seekToEndOfFile Positions the current file offset at the end of the file
 -(void) truncateFileAtOffset: offset Sets the file size to offset bytes (pad if needed)
 -(void) closeFile Closes the file
 
 
 
 
 
 The method readDataToEndOfFile: reads up to UINT_MAX bytes of data at a time, which is defined in <limits.h> and equal to FFFFFFFF16.This will be large enough for any application you’ll have to write.You can also break up the operation to perform smaller-sized reads and writes.You can even set up a loop to transfer a buffer full of bytes between the files at a time, using the readDataOfLength: method.
 
 
 
 
 
 
 If you open a file for updating, the file offset is set to the beginning of the file.You can change that offset by seeking within a file and then perform your read or write opera- tions on the file. So, to seek to the 10th byte in a file whose handle is databaseHandle, you can write the following message expression:
 [databaseHandle seekToFileOffset: 10];
 Relative file positioning is done by obtaining the current file offset and then adding to or subtracting from it. So, to skip over the next 128 bytes in the file, write the following:
 [databaseHandle seekToFileOffet: [databaseHandle offsetInFile] + 128];
 And to move back the equivalent of five integers in the file, write this:
 [databaseHandle seekToFileOffet:[databaseHandle offsetInFile] – 5 * sizeof (int)];
 */



-(void)testNSFileHandler{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSFileHandle *inFile, *outFile;
    NSData *buffer;
    // Open the file testfile for reading
    inFile = [NSFileHandle fileHandleForReadingAtPath: @"testfile"];
    if (inFile == nil) {
        NSLog (@"Open of testfile for reading failed");
        return;
    }
    // Create the output file first if necessary 
    [[NSFileManager defaultManager] createFileAtPath: @"testout" contents: nil attributes: nil];
    // Now open outfile for writing
    outFile = [NSFileHandle fileHandleForWritingAtPath: @"testout"];
    if (outFile == nil) {
        NSLog (@"Open of testout for writing failed");
        return;
    }
    // Truncate the output file since it may contain data
    [outFile truncateFileAtOffset: 0];
    // Read the data from inFile and write it to outFile
    buffer = [inFile readDataToEndOfFile];
    [outFile writeData: buffer];
    // Close the two files
    [inFile closeFile]; [outFile closeFile];
    // Verify the file's contents
    NSLog(@"%@", [NSString stringWithContentsOfFile: @"testout" encoding: NSUTF8StringEncoding error: nil]);
    [pool drain]; 
    
}


-(void)testFileHandlerAppend{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSFileHandle  *inFile, *outFile;
    NSData  *buffer;
    // Open the file fileA for reading
    inFile = [NSFileHandle fileHandleForReadingAtPath: @"fileA"];
    if (inFile == nil) {
        NSLog (@"Open of fileA for reading failed");
        return;
    }
    // Open the file fileB for updating
    outFile = [NSFileHandle fileHandleForWritingAtPath: @"fileB"];
    if (outFile == nil) {
        NSLog (@"Open of fileB for writing failed");
        return;
    }
    // Seek to the end of outFile
    [outFile seekToEndOfFile];
    // Read inFile and write its contents to outFile
    buffer = [inFile readDataToEndOfFile]; 
    [outFile writeData: buffer];
    // Close the two files
    [inFile closeFile];
    [outFile closeFile];
    // verify its contents
    NSLog(@"%@", [NSString stringWithContentsOfFile: @"fileB" encoding: NSUTF8StringEncoding error: nil]);
    [pool drain];     
}


@end
